package com.cci.kangdao.aop;

import com.cci.kangdao.dao.model.UserT;
import com.cci.kangdao.redis.RedisClientUtils;
import com.cci.kangdao.utilTool.ParameterTool;
import com.cci.kangdao.utilTool.RequestContextHolder;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 禁止重复提交拦截器
 * @author William Du
 * @date 2020/4/27
 */
@Component
@Aspect
@Order(Ordered.HIGHEST_PRECEDENCE+1)
public class NoDuplicateSubmissionIntercept {

    private static final Logger logger = Logger.getLogger(NoDuplicateSubmissionIntercept.class);

    @Autowired
    private RedisClientUtils redisClientUtils;
    /**
     * 拦截postJson相关请求
     * @param proceedingJoinPoint
     * @return
     */
    @Around("(@annotation(com.cci.kangdao.aop.annotation.NoDuplicateSubmission))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        HttpServletRequest request = RequestContextHolder.getRequest();
        HttpServletResponse response = RequestContextHolder.getResponse();
        UserT userT = UserThreadLocal.get();
        Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        String lockKey = targetMethod.getName() + userT.getId();  //redis分布式锁key名
        System.out.println(lockKey);
        try {
            // TODO: 2020/10/14 1.获取用户信息；2.获取执行方法；3.对当前方法当前用户在reids中加分布式锁；4.成功，进行后续流程，正常响应结束删除锁；5.失败，直接响应
            // 加锁处理，避免发生多次提交。
            if(!redisClientUtils.lock(lockKey,60L)){
                ParameterTool.writeErrorResponse(response,-98);
                return null;
            }
            Object res =  proceedingJoinPoint.proceed();
            //此处删除锁
            redisClientUtils.delkey(lockKey);
            return res;
        } catch (Throwable throwable) {
            // 删除锁操作
            redisClientUtils.delkey(lockKey);
            logger.error(throwable.getMessage(), throwable);
            ParameterTool.writeErrorResponse(RequestContextHolder.getResponse());
        }
        return null;
    }



}
